<template>
  <div
    class="dh-form-item"
    :class="{
      'is-error': ValidateStatus.status === 'error',
      'is-success': ValidateStatus.status === 'success',
      'is-loading': ValidateStatus.isLoding,
      'is-required':isRequired
    }"
  >
    <div class="dh-form-item__label">
      <slot name="label" :label="label">
        {{ label }}
      </slot>
    </div>
    <div class="dh-form-item__content">
      <slot :validate="validate"></slot>
      <div
        class="dh-form-item__error-msg"
        v-if="ValidateStatus.status === 'error'"
      >
        {{ ValidateStatus.errorMsg }}
      </div>
    </div>

  
  </div>
</template>

<script setup lang="ts">
import {
  ref,
  provide,
  inject,
  computed,
  reactive,
  onMounted,
  onUnmounted,
} from "vue";
import { FormContextKey } from "./type";
import { isNil } from "lodash-es";
import type { FormItemProps, FormItemContext , FormItemInstance , FormItemStatus } from "./type";
import { FormItemContextKey } from "./type";
import Schema from "async-validator";
defineOptions({
  name: "DhFormItem",
});
let ValidateStatus = reactive<FormItemStatus>({
  status: "init",
  errorMsg: "",
  isLoding: false,
});
let cszValue = ref("");
//接收数据
const props = defineProps<FormItemProps>();
//接收父组件传入的数据
const formContext = inject(FormContextKey);

//计算出是否有该属性
const innerValue = computed(() => {
  let model = formContext?.model;
  //   model必须有 props接收的prop也要有
  // 判断传入的model里是否有和prpp对应的属性
  if (model && props.prop && !isNil(model[props.prop])) {
    //如果有就返回对应的属性
    return model[props.prop];
  } else {
    //没有的话就返回null
    return null;
  }
});
//计算对应规则
const innerRules = computed(() => {
  let rules = formContext?.rules;
  // rules必须有 props接收的prop也要有
  // 判断传入的rules里是否有和prpp对应的属性
  if (rules && props.prop && !isNil(rules[props.prop])) {
    //如果有就返回对应的属性
    return rules[props.prop];
  } else {
    //没有的话就返回一个空数组
    return [];
  }
});
const isRequired = computed(()=>{
  return innerRules.value.some((rule:any)=>rule.required)
})
const TriggerMthod = (tirgger: string) => {
  const rules = innerRules.value;
  if (rules) {
    return rules.filter((rule: any) => {
      if (!rule.trigger || !tirgger) return true;
      return rule.trigger && rule.trigger == tirgger;
    });
  } else {
    return [];
  }
};
//校验
const validate = async (tirgger?: string) => {
  let modelName = props.prop;
  let rules = TriggerMthod(tirgger!);

  if (rules.length == 0) return true;
  if (modelName) {
    let formValidate = new Schema({ [modelName]: rules });
    ValidateStatus.isLoding = true;
    return formValidate
      .validate({
        [modelName]: innerValue.value,
      })
      .then(() => {
        ValidateStatus.status = "success";
      })
      .catch((err) => {
        ValidateStatus.status = "error";
        ValidateStatus.errorMsg =
          err && err.errors.length > 0 ? err.errors[0].message : "";
        return Promise.reject(err);
      })
      .finally(() => {
        ValidateStatus.isLoding = false;
      });
  }
};
let FormItem: FormItemContext = {
  validate,
};

//清除
const clearValidate = () => {
  Object.assign(ValidateStatus, {
    status: "init",
    errorMsg: "",
    isLoding: false,
  });
};
//重置
const resetField = () => {
  clearValidate()
  let model = formContext?.model;
  //   model必须有 props接收的prop也要有
  // 判断传入的model里是否有和prpp对应的属性
  if (model && props.prop && !isNil(model[props.prop])) {
    model[props.prop] = cszValue.value
  }
}
const context = {
  prop: props.prop || "",
  validate,
  clearValidate,
  resetField
};
onMounted(() => {
  if (props.prop) {
    formContext?.addField!(context);
  }
  cszValue.value = innerValue.value
});
//注入
provide(FormItemContextKey, FormItem);
defineExpose<FormItemInstance> ({
  validate,
  clearValidate,
  resetField,
  status:ValidateStatus
})
onUnmounted(() => {
  formContext?.removeField!(context);
});
</script>

<style scoped></style>
